/***********************************************************************************
 * 文件名： bstc.h
 * 作者： 刘言
 * 版本： 1
 * 说明：
 *      面向对象设计的升压控制器，便于多路升压控制。升压电路的驱动，通过电压值反馈调整PWM
 * 占空比达到升压，并恒定电压的目的。不要与单例模式的 boost_controller 同时使用。
 *      提供以下功能：
 *          升压输出；
 *          电压调节；
 *          过流保护和通知；
 *          过载通知；
 *          开路保护和通知【未实现】。
 * 修改记录：
 * 	2022/07/15: 初版。 刘言。
***********************************************************************************/
#ifndef _BSTC_H_
#define _BSTC_H_

#ifdef __cplusplus
 extern "C" {
#endif 

#include "bstc_config.h"
#include "components\ly_pid\ly_pid.h"
#include "polsys.h"

// 自定义类型

typedef enum _boostc_event_t
{
    BSTC_EV_NULL = 0,               
    // BSTC_EV_OVER_TEMP = (1<<0),          // 温度过高【未实现】
    // BSTC_EV_OVER_LOAD = (1<<1),          // 过载，输出电压过低【未实现】
    BSTC_EV_SHORT_OUT = (1<<2),          // 短路、过流了，已经停止输出
    // BSTC_EV_NO_BOOST = (1<<3),           // 未升压，目标电压过低，无需升压就能达到或者超过【未实现】
    // BSTC_EV_STARTED = (1<<4),            // 已（成功）启动，注意本事件在中断中调用，注意处理代码耗时【未实现】
    BSTC_EV_END
}boostc_event_t;

#if (_BSTC_FULL_ADV > 256)
typedef u16 bstc_adv_t;
#else
typedef u8 bstc_adv_t;
#endif

#if (_BSTC_FULL_PWM_VALUE > 255)
typedef u16 bstc_pwmv_t;
#else
typedef u8 bstc_pwmv_t;
#endif

// 事件回调方法的类型
typedef void (*bstc_callback_fun_t)(boostc_event_t e);

// 设置硬件PWM的方法的类型
typedef void (*bstc_set_pwm_fun_t)(bstc_pwmv_t new_pwm);

// 通用无参数无返回值方法的类型
typedef void (*bstc_normal_fun_t)();

// 初始化参数结构体，便于一次传入多个参数
typedef struct _bstc_init_param
{
    pid_kp_t kp;    // PID 比例系数
    pid_ki_t ki;    // PID 积分系数
    pid_kd_t kd;    // PID 微分系数
    bstc_pwmv_t MaxPwmValue;    // 最大PWM值
    u8 OcAllowCount;            // 允许的过流次数
    bstc_adv_t TargetADV;       // 目标AD值，要维持的输出电压的AD值
// 以下是需要的API
    bstc_callback_fun_t EventCallBack;  // 事件回调函数，当有事件发生时会被调用
    bstc_normal_fun_t InitPwm;  // PWM控制器初始化（BSTC初始化时被调用）
    bstc_set_pwm_fun_t SetPwm;  // 设置硬件PWM值的方法，每次更新PWM值时被调用
    bstc_normal_fun_t InitAdc;  // ADC初始化（BSTC初始化时被调用）
    bstc_normal_fun_t RunAdc;   // ADC开始（定时）运行（BSTC启动升压时被调用），调用后要求ADC能不断的采集并调用 BSTC_EvNewFBV 或 BSTC_EvOverCurrent
    bstc_normal_fun_t StopAdc;  // ADC停止（定时）运行（BSTC停止升压时被调用）
}bstc_init_param;

typedef bstc_init_param *bstc_init_param_t;

// bstc 类
typedef struct _bstc
{
    ly_pid mLyPid;              // PID算法计算器（直接内部包含对象实体，放在第一个位置可以当做继承。也可以考虑改为ly_pid_t类型，即这里不包含实体，仅指向一个ly_pid对象）
    bool mRun;                  // 是否正在运行
    bstc_pwmv_t mMaxPwmValue;   // 最大PWM值
    bstc_pwmv_t mPwmValue;      // 当前PWM值
    boostc_event_t mEvent;      // 当前待通知事件，最新发生的事件。
    u8 mOcCount;                // 检测到MOS过流的次数。
    u8 mOcAllowCount;           // 允许的过流次数
    bstc_adv_t mTargetADV;      // 目标AD值，要维持的输出电压的AD值
    bstc_adv_t mNowADV;         // 当前实际AD值
// 以下是需要的API
    bstc_callback_fun_t EventCallBack;  // 事件回调函数，当有事件发生时会被调用
    // bstc_normal_fun_t InitPwm;  // PWM控制器初始化（BSTC初始化时被调用）,注意：初始化默认PWM为最低或者不输出。[不需要保存]
    bstc_set_pwm_fun_t SetPwm;  // 设置硬件PWM值的方法，每次更新PWM值时被调用，注意：设置为0时要求立即刹车
    // bstc_normal_fun_t InitAdc;  // ADC初始化（BSTC初始化时被调用）【不需要保存】
    bstc_normal_fun_t RunAdc;   // ADC开始（定时）运行（BSTC启动升压时被调用），调用后要求ADC能不断的采集并调用 BSTC_EvNewFBV 或 BSTC_EvOverCurrent
    bstc_normal_fun_t StopAdc;  // ADC停止（定时）运行（BSTC停止升压时被调用）
}bstc;

typedef bstc *bstc_t;



// APIs

#ifdef POLSYS_LITE
// 必须定时间隔调用，建议间隔10ms调用一次
void BSTC_loop();
#endif

// 由外部调用（一般是ADC中断）来通知 BSTC 采集到了新的输出电压反馈脚的AD值。
// 建议AD采集间隔40~100us，在采集完成中断中调用。
// this: 要通知的 bstc 对象
// adv: 最新采集到的AD值
void BSTC_evNewFBV(bstc_t this, bstc_adv_t adv);

// MOS管电流过大事件，由外部调用，通知 BSTC。
// 一般是由电压比较器或者ADC产生中断在中断中调用，可以不调用。
// this: 要通知的 bstc 对象
void BSTC_evOverCurrent(bstc_t this);

// 初始化
// this: 要初始化的 bstc 对象
// init_param: 要用于初始化的参数
// 注意：此函数应理解为C++的构造函数，一个对象只能调用一次，不要重复调用。
void BSTC_init(bstc_t this, bstc_init_param_t init_param);

// 开始升压，注意确保已经设置了合适的 Target 。
// this: 要操作的 bstc 对象
// start_pwm: 启动时的PWM值
void BSTC_start(bstc_t this, bstc_pwmv_t start_pwm);

// 设置目标AD值（用于改变输出电压）
// this: 要操作的 bstc 对象
// target_adv: 目标AD值
// 使用者需要自行计算目标电压对应的AD值.
// 一个比较好的方式是使用宏定义获取AD值，比如：
// #define GET_ADV(voltage)     ((u32)voltage*FBRL*FULL_ADV)/((u32)(FBRH + FBRL)*ADC_VREF)
// BSTC_SetTarget(bstc_obj, GET_ADV(voltage));
// 其中 FBRL FBRH 分别是低侧、高侧反馈分压电阻的比例， FULL_ADV 是ADC满值， ADC_VREF 是ADC参考电压。
STATIC_FORCE_IN_LINE void BSTC_setTarget(bstc_t this, bstc_adv_t target_adv)
{
    this->mTargetADV = target_adv;
}

// 停止升压，开关立即截止
// this: 要操作的 bstc 对象
void BSTC_stop(bstc_t this);   

#ifdef _BSTC_USE_EXT_CAL_ADV
// 获取当前实际AD值
// this: 要操作的 bstc 对象
// 可用于计算当前实际电压值
bstc_adv_t BSTC_getNowADV(bstc_t this);
#else
// 获取当前实际输出电压，启动1ms之后才能获取准确的值，单位mV
u16 BSTC_getNowVoltage(bstc_t this);
#endif

// 获取是否正在运行
// this: 要操作的 bstc 对象
STATIC_FORCE_IN_LINE bool BSTC_isRun(bstc_t this)
{
    return this->mRun;
}

// 设置最大PWM值
// this: 要操作的 bstc 对象
// value: 要设置的值
STATIC_FORCE_IN_LINE void BSTC_setMaxPwmValue(bstc_t this, bstc_pwmv_t value)
{
    this->mMaxPwmValue = value;
}

#ifdef __cplusplus
}
#endif 

#endif



